<template>
  <div class="print-map" @click.stop>
    <div class="drag-handle" @mousedown="startDrag">
      <el-icon>
        <DArrowLeft />
      </el-icon>
      <span>拖动</span>
    </div>

    <el-card class="print-panel">
      <template #header>
        <div class="card-header">
          <div class="header-left">
            <span>打印地图</span>
          </div>
          <div class="header-right">
            <el-button type="primary" size="small" @click="handlePrint">打印</el-button>
            <el-button type="danger" size="small" @click="handleClose">
              <el-icon>
                <Close />
              </el-icon>
            </el-button>
          </div>
        </div>
      </template>

      <div class="print-content">
        <div class="print-settings">
          <!-- 图件信息 -->
          <div class="section">
            <h4>图件信息</h4>
            <el-form ref="printFormRef" :model="printSettings" :rules="printFormRules" label-width="80px" size="small">
              <el-form-item label="标题" prop="title">
                <el-input v-model="printSettings.title" placeholder="请输入标题"></el-input>
              </el-form-item>
              <el-form-item label="制图日期" prop="date">
                <el-date-picker v-model="printSettings.date" type="date" placeholder="选择日期" format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"></el-date-picker>
              </el-form-item>
              <el-form-item label="制图单位" prop="unit">
                <el-input v-model="printSettings.unit" placeholder="请输入单位"></el-input>
              </el-form-item>
            </el-form>
          </div>

          <!-- 地图要素 -->
          <div class="section">
            <h4>地图要素</h4>
            <el-form :model="printSettings.elements" label-width="80px" size="small">
              <el-form-item>
                <el-checkbox v-model="printSettings.elements.compass">指北针</el-checkbox>
                <el-checkbox v-model="printSettings.elements.scale">比例尺</el-checkbox>
                <el-checkbox v-model="printSettings.elements.legend">图例</el-checkbox>
              </el-form-item>
            </el-form>
          </div>

          <!-- 打印设置 -->
          <div class="section">
            <h4>打印设置</h4>
            <el-form :model="printSettings.output" label-width="80px" size="small">
              <el-form-item label="纸张样式">
                <el-select v-model="printSettings.output.paperStyle">
                  <el-option label="A4横向" value="A4-landscape"></el-option>
                  <el-option label="A4纵向" value="A4-portrait"></el-option>
                  <el-option label="A3横向" value="A3-landscape"></el-option>
                  <el-option label="A3纵向" value="A3-portrait"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="导出格式">
                <el-select v-model="printSettings.output.format">
                  <el-option label="PNG" value="png"></el-option>
                  <el-option label="JPEG" value="jpeg"></el-option>
                  <el-option label="PDF" value="pdf"></el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </div>
        </div>
        <!-- 添加预览区域 -->
        <div class="preview-container">
          <div ref="previewMapRef" class="preview-map"></div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
import { ScaleLine, defaults as defaultControls } from 'ol/control'
import { toJpeg, toPng } from 'html-to-image'
import jsPDF from 'jspdf'
import Map from 'ol/Map'
import View from 'ol/View'
import { DArrowLeft, Close } from '@element-plus/icons-vue'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import { ElMessage } from 'element-plus'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'

const props = defineProps({
  map: {
    type: Object,
    required: true
  }
})

const emit = defineEmits(['close'])

// 处理关闭
const handleClose = () => {
  emit('close')
}

// 打印设置
const printSettings = ref({
  title: '',
  date: new Date().toISOString().split('T')[0],
  unit: '',
  elements: {
    compass: true,
    scale: true,
    legend: true
  },
  output: {
    paperStyle: 'A4-landscape',
    format: 'png'
  }
})

// 预览地图实例
const previewMapRef = ref(null)
let previewMap = null

// 纸张尺寸配置（单位：毫米）
const paperSizes = {
  'A4-landscape': { width: 297, height: 210 },
  'A4-portrait': { width: 210, height: 297 },
  'A3-landscape': { width: 420, height: 297 },
  'A3-portrait': { width: 297, height: 420 }
}

// 添加指北针控件
const addCompass = () => {
  if (!previewMap) return

  // 移除已有的指北针
  const existingCompass = document.querySelector('.preview-compass')
  if (existingCompass) {
    existingCompass.remove()
  }

  if (printSettings.value.elements.compass) {
    const compass = document.createElement('div')
    compass.className = 'preview-compass'
    Object.assign(compass.style, {
      position: 'absolute',
      top: '20px',
      right: '20px',
      width: '40px',
      height: '40px',
      backgroundColor: 'rgba(255, 255, 255, 0.8)',
      borderRadius: '4px',
      boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      justifyContent: 'center',
      zIndex: '1000'
    })
    compass.innerHTML = `
      <div style="
        font-size: 24px;
        line-height: 1;
        color: #409EFF;
        font-weight: bold;
      ">↑</div>
      <div style="
        font-size: 12px;
        color: #666;
        margin-top: 2px;
      ">N</div>
    `
    const mapContainer = previewMapRef.value.querySelector('.ol-viewport')
    if (mapContainer) {
      mapContainer.appendChild(compass)
    }
  }
}

// 初始化预览地图
const initPreviewMap = async () => {
  if (!props.map || !previewMapRef.value) {
    throw new Error('缺少必要参数')
  }

  try {
    // 获取当前地图的视图状态
    const currentView = props.map.getView()
    if (!currentView) {
      throw new Error('无法获取地图视图')
    }

    // 克隆图层
    const currentLayers = props.map.getLayers().getArray().map(layer => {
      // 克隆图层
      if (layer instanceof VectorLayer) {
        // 如果是矢量图层（标绘图层），克隆要素
        const newSource = new VectorSource({
          features: layer.getSource().getFeatures().map(feature => feature.clone())
        })
        return new VectorLayer({
          source: newSource,
          style: layer.getStyle(),
          visible: layer.getVisible(),
          zIndex: layer.getZIndex()
        })
      } else {
        // 其他图层（如底图）的处理保持不变
        const sourceUrls = layer.getSource().getUrls?.()?.[0] || layer.getSource().getUrl?.()
        if (!sourceUrls) return null

        return new TileLayer({
          source: new XYZ({
            url: sourceUrls,
            projection: layer.getSource().getProjection(),
            crossOrigin: 'anonymous',
            wrapX: true,
            transition: 0,
            tileGrid: layer.getSource().getTileGrid()
          }),
          visible: layer.getVisible(),
          zIndex: layer.getZIndex()
        })
      }
    }).filter(layer => layer !== null)

    // 创建预览地图
    previewMap = new Map({
      target: previewMapRef.value,
      layers: currentLayers,
      view: new View({
        center: currentView.getCenter(),
        zoom: currentView.getZoom(),
        projection: currentView.getProjection(),
        extent: currentView.calculateExtent(),
        constrainResolution: true,
        maxZoom: 18,
        minZoom: 1
      }),
      controls: defaultControls({
        zoom: true,
        rotate: false,
        attribution: false
      })
    })

    // 添加比例尺
    if (printSettings.value.elements.scale) {
      previewMap.addControl(new ScaleLine({
        units: 'metric',
        bar: true,
        steps: 4,
        text: true,
        minWidth: 140
      }))
    }

    // 添加指北针
    addCompass()

    // 步视图
    const syncViews = () => {
      const mainView = props.map.getView()
      previewMap.getView().setCenter(mainView.getCenter())
      previewMap.getView().setZoom(mainView.getZoom())
    }

    // 监听主地图视图变化
    props.map.getView().on('change:center', syncViews)
    props.map.getView().on('change:resolution', syncViews)

    // 监听预览地图视图变化
    previewMap.getView().on('change:center', () => {
      const previewView = previewMap.getView()
      props.map.getView().setCenter(previewView.getCenter())
    })
    previewMap.getView().on('change:resolution', () => {
      const previewView = previewMap.getView()
      props.map.getView().setZoom(previewView.getZoom())
    })

    // 等待地图初始化完成
    await new Promise(resolve => setTimeout(resolve, 1000))
    previewMap.renderSync()

    return previewMap
  } catch (error) {
    console.error('初始化预览地图失败:', error)
    throw new Error('初始化预览地图失败')
  }
}

// 监听打印设置变化
watch(() => printSettings.value.elements.scale, (newValue) => {
  if (previewMap) {
    // 移除所有比例尺控件
    const controls = previewMap.getControls().getArray()
    controls.forEach(control => {
      if (control instanceof ScaleLine) {
        previewMap.removeControl(control)
      }
    })

    // 如果需要，添加新的比例尺
    if (newValue) {
      previewMap.addControl(new ScaleLine({
        units: 'metric',
        bar: true,
        steps: 4,
        text: true,
        minWidth: 140
      }))
    }
  }
})

// 监听地图变化
watch(() => props.map, () => {
  if (props.map) {
    initPreviewMap()
  }
})

// 组件挂载时初始化预览地图
onMounted(() => {
  initPreviewMap()
})

// 组件卸载时清理
onUnmounted(() => {
  if (previewMap) {
    previewMap.setTarget(null)
    previewMap = null
  }
})

// 添加表单校验规则
const printFormRules = {
  title: [
    { required: true, message: '请输入标题', trigger: 'blur' }
  ],
  date: [
    { required: true, message: '请选择制图日期', trigger: 'change' }
  ],
  unit: [
    { required: true, message: '请输入制图单位', trigger: 'blur' }
  ]
}

// 添加表单用
const printFormRef = ref(null)

// 修改打印处理函数
const handlePrint = async () => {
  try {
    await printFormRef.value.validate()
  } catch (error) {
    ElMessage.warning('请完善图件信息')
    return
  }

  try {
    // 使用地图的 canvas 元素
    const mapCanvas = previewMapRef.value.querySelector('canvas')
    if (!mapCanvas) {
      throw new Error('找不到地图画布')
    }

    // 创建临时 canvas
    const canvas = document.createElement('canvas')
    canvas.width = 1920
    canvas.height = 1080
    const ctx = canvas.getContext('2d')

    // 绘制地图
    ctx.fillStyle = '#ffffff'
    ctx.fillRect(0, 0, canvas.width, canvas.height)
    ctx.drawImage(mapCanvas, 0, 0, canvas.width, canvas.height)

    // 绘制标题
    ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'
    ctx.fillRect(canvas.width / 2 - 200, 20, 400, 50)
    ctx.strokeStyle = 'rgba(200, 200, 200, 0.5)'
    ctx.strokeRect(canvas.width / 2 - 200, 20, 400, 50)

    ctx.fillStyle = '#333'
    ctx.font = 'bold 24px Arial'
    ctx.textAlign = 'center'
    ctx.fillText(printSettings.value.title, canvas.width / 2, 52)

    // 绘制日期和单位（右下角）
    ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'
    const dateUnitWidth = 300
    const dateUnitHeight = 70
    const padding = 20
    ctx.fillRect(
      canvas.width - dateUnitWidth - padding,
      canvas.height - dateUnitHeight - padding,
      dateUnitWidth,
      dateUnitHeight
    )
    ctx.strokeStyle = 'rgba(200, 200, 200, 0.5)'
    ctx.strokeRect(
      canvas.width - dateUnitWidth - padding,
      canvas.height - dateUnitHeight - padding,
      dateUnitWidth,
      dateUnitHeight
    )

    ctx.font = '18px Arial'
    ctx.textAlign = 'right'
    ctx.fillStyle = '#666'
    ctx.fillText(
      printSettings.value.unit,
      canvas.width - 30,
      canvas.height - 55
    )
    ctx.fillText(
      printSettings.value.date,
      canvas.width - 30,
      canvas.height - 25
    )

    // 添加指北针
    if (printSettings.value.elements.compass) {
      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'
      ctx.fillRect(canvas.width - 80, 20, 60, 60)
      ctx.strokeStyle = '#ddd'
      ctx.strokeRect(canvas.width - 80, 20, 60, 60)

      ctx.fillStyle = '#409EFF'
      ctx.font = 'bold 36px Arial'
      ctx.textAlign = 'center'
      ctx.fillText('↑', canvas.width - 50, 55)
      
      ctx.fillStyle = '#666'
      ctx.font = '16px Arial'
      ctx.fillText('N', canvas.width - 50, 75)
    }

    // 添加比例尺
    if (printSettings.value.elements.scale) {
      // 获取当前地图的分辨率和比例尺
      const resolution = previewMap.getView().getResolution()
      const meterPerUnit = 111319.49079327358  // EPSG:4326 的每单位米数
      const scaleValue = resolution * meterPerUnit
      
      // 计算合适的比例尺长度
      let scaleLength, scaleUnit
      if (scaleValue >= 1000) {
        scaleLength = Math.round(scaleValue / 1000)
        scaleUnit = 'km'
      } else {
        scaleLength = Math.round(scaleValue)
        scaleUnit = 'm'
      }

      // 绘制比例尺
      const scaleWidth = 200
      const scaleHeight = 40
      
      // 绘制比例尺背景
      ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'
      ctx.fillRect(
        padding,
        canvas.height - scaleHeight - padding,
        scaleWidth,
        scaleHeight
      )
      ctx.strokeStyle = 'rgba(200, 200, 200, 0.5)'
      ctx.strokeRect(
        padding,
        canvas.height - scaleHeight - padding,
        scaleWidth,
        scaleHeight
      )

      // 绘制比例尺线
      const lineY = canvas.height - padding - scaleHeight/2
      ctx.strokeStyle = '#333'
      ctx.lineWidth = 2
      ctx.beginPath()
      
      // 绘制主线
      ctx.moveTo(padding + 20, lineY)
      ctx.lineTo(padding + scaleWidth - 20, lineY)
      
      // 绘制端点竖线
      ctx.moveTo(padding + 20, lineY - 5)
      ctx.lineTo(padding + 20, lineY + 5)
      ctx.moveTo(padding + scaleWidth - 20, lineY - 5)
      ctx.lineTo(padding + scaleWidth - 20, lineY + 5)
      
      ctx.stroke()

      // 绘制比例尺文字
      ctx.font = '14px Arial'
      ctx.fillStyle = '#333'
      ctx.textAlign = 'center'
      ctx.fillText(
        `${scaleLength} ${scaleUnit}`,
        padding + scaleWidth/2,
        lineY + 20
      )
    }

    // 导出图片
    let output
    switch (printSettings.value.output.format) {
      case 'png':
        output = canvas.toDataURL('image/png')
        downloadImage(output, 'map.png')
        break
      case 'jpeg':
        output = canvas.toDataURL('image/jpeg', 0.95)
        downloadImage(output, 'map.jpg')
        break
      case 'pdf':
        output = canvas.toDataURL('image/png')
        const pdf = new jsPDF({
          orientation: printSettings.value.output.paperStyle.includes('landscape') ? 'landscape' : 'portrait',
          unit: 'mm',
          format: printSettings.value.output.paperStyle.split('-')[0]
        })

        const pdfWidth = pdf.internal.pageSize.getWidth() - 20
        const pdfHeight = pdf.internal.pageSize.getHeight() - 20
        pdf.addImage(output, 'PNG', 10, 10, pdfWidth, pdfHeight)
        pdf.save('map.pdf')
        break
    }

  } catch (error) {
    console.error('打印失败:', error)
    ElMessage.error(error.message || '打印失败')
  }
}

// 下载图片辅助函数
const downloadImage = (dataUrl, filename) => {
  const link = document.createElement('a')
  link.href = dataUrl
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 修改初始位置计算
const calculateInitialPosition = () => {
  const viewportWidth = window.innerWidth
  const viewportHeight = window.innerHeight

  // 组件尺寸（像素）
  const componentWidth = 1000  // 固定宽度
  const componentHeight = 600  // 固定高度
  const topMargin = 150        // 顶部边距

  // 计算居中位置（像素）
  return {
    x: Math.max(0, (viewportWidth - componentWidth) / 2),
    y: Math.max(topMargin, (viewportHeight - componentHeight) / 2)  // 添加最小顶部边距
  }
}

// 拖动相关状态
const isDragging = ref(false)
const dragOffset = ref({ x: 0, y: 0 })
const position = ref(calculateInitialPosition())

// 监听窗口大小变化，重新计算位置
const handleResize = () => {
  if (!isDragging.value) {
    position.value = calculateInitialPosition()
  }
}

// 添加窗口大小变化监听
onMounted(() => {
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
  if (previewMap) {
    previewMap.setTarget(null)
    previewMap = null
  }
})

// 开始拖动
const startDrag = (event) => {
  isDragging.value = true
  dragOffset.value = {
    x: event.clientX - position.value.x,
    y: event.clientY - position.value.y
  }

  // 添加全事件监听
  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('mouseup', stopDrag)
}

// 处理拖动
const handleDrag = (event) => {
  if (!isDragging.value) return

  // 计算新位置
  position.value = {
    x: event.clientX - dragOffset.value.x,
    y: event.clientY - dragOffset.value.y
  }

  // 确保不超出视窗边界
  const container = document.querySelector('.print-map')
  if (container) {
    const rect = container.getBoundingClientRect()
    const viewportWidth = window.innerWidth
    const viewportHeight = window.innerHeight
    const topMargin = 50  // 与上面保持一致

    // 限制左右边界
    if (position.value.x < 0) position.value.x = 0
    if (position.value.x + rect.width > viewportWidth) {
      position.value.x = viewportWidth - rect.width
    }

    // 限制上下边界，考虑顶部边距
    if (position.value.y < topMargin) position.value.y = topMargin
    if (position.value.y + rect.height > viewportHeight) {
      position.value.y = viewportHeight - rect.height
    }
  }
}

// 停止拖动
const stopDrag = () => {
  isDragging.value = false
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
}

// 监听指北针设置变化
watch(() => printSettings.value.elements.compass, (newValue) => {
  addCompass()
})
</script>

<style lang="scss" scoped>
.print-map {
  padding: vw(5);
  min-width: vw(300);
  max-width: vw(1000);
  width: vw(1000);
  height: vw(600);
  position: fixed; // 改为 fixed 定位
  left: v-bind('position.x + "px"');
  top: v-bind('position.y + "px"');
  z-index: 1000;
  user-select: none; // 防止拖动时选中文本
}

.drag-handle {
  position: absolute;
  top: vw(-30);
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(64, 158, 255, 0.8);
  color: white;
  padding: vw(5) vw(15);
  border-radius: vw(4) vw(4) 0 0;
  cursor: move;
  display: flex;
  align-items: center;
  gap: vw(5);
  font-size: vw(14);

  &:hover {
    background-color: rgba(64, 158, 255, 1);
  }

  .el-icon {
    font-size: vw(16);
  }
}

.print-panel {
  height: 100%;

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .header-left {
      font-size: vw(16);
      font-weight: bold;
    }

    .header-right {
      display: flex;
      gap: vw(8);

      .el-button {
        padding: vw(6) vw(12);

        .el-icon {
          margin: 0;
        }
      }
    }
  }
}

.preview-container {
  margin: vw(10) 0;
  border: 1px solid #ddd;
  border-radius: vw(4);
  overflow: hidden;
  flex: 1;
}

.preview-map {
  width: 100%;
  height: 100%;
  background: #f5f5f5;
}

.print-settings {
  width: vw(300);
  height: vw(500);

  .section {
    margin-bottom: vw(15);

    h4 {
      margin: vw(10) 0;
      font-size: vw(14);
      color: #666;
    }
  }
}

:deep(.el-form-item) {
  margin-bottom: vw(12);
}

:deep(.el-input),
:deep(.el-select),
:deep(.el-date-picker) {
  width: 100%;
}

:deep(.el-checkbox) {
  margin-right: vw(15);
}

/* 打印样式 */
.ol-compass {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 40px;
  height: 40px;
  text-align: center;

  .compass-arrow {
    font-size: 24px;
    line-height: 1;
  }

  .compass-text {
    font-size: 12px;
  }
}

.print-info {
  position: absolute;
  top: 10px;
  left: 10px;
  background: rgba(255, 255, 255, 0.9);
  padding: 10px;
  border-radius: 4px;
  z-index: 1000;

  h2 {
    margin: 0 0 5px;
    font-size: 14px;
  }

  .print-metadata {
    font-size: 12px;
    color: #666;

    span {
      display: block;
      margin-bottom: 3px;
    }
  }
}

.print-content {
  display: flex;
  flex-direction: row;
  gap: vw(50);
}

/* 拖动时的样式 */
.print-map {
  &:active {
    cursor: move;
  }
}

/* 止地图和表单在拖动时被选中 */
.preview-map,
.print-settings {
  pointer-events: auto;
}

.preview-compass {
  position: absolute;
  top: vw(20);
  right: vw(20);
  width: vw(40);
  height: vw(40);
  background-color: rgba(255, 255, 255, 0.8);
  border-radius: vw(4);
  box-shadow: 0 vw(2) vw(4) rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 1000;

  .compass-arrow {
    font-size: vw(24);
    line-height: 1;
    color: #409EFF;
    font-weight: bold;
  }

  .compass-text {
    font-size: vw(12);
    color: #666;
    margin-top: vw(2);
  }
}
</style>